/**
 *
 */
package com.angel.io.processors.runners.imports.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.log4j.Logger;

import com.angel.common.helpers.AnnotationHelper;
import com.angel.common.helpers.CollectionHelper;
import com.angel.io.annotations.ColumnRow;
import com.angel.io.annotations.RowProcessorCommand;
import com.angel.io.descriptor.FileProcessorDescriptor;
import com.angel.io.processors.commands.impl.AnnotationImportRowProcessorCommand;
import com.angel.io.processors.commands.imports.ImportFileProcessorCommand;
import com.angel.io.type.rows.ImportRowFile;
import com.angel.io.validators.RowProcessorCommandValidator;
import com.angel.io.validators.impl.ColumnsParametersRowCheckerAnnotationValidator;
import com.angel.io.validators.impl.ColumnsParametersRowProcessorAnnotationValidator;
import com.angel.io.validators.impl.ColumnsPositionRowCheckerAnnotationValidator;
import com.angel.io.validators.impl.ColumnsPositionRowProcessorAnnotationValidator;
import com.angel.io.validators.impl.DefaultConstructorRowProcessorCommandValidator;
import com.angel.io.validators.impl.InjectObjectPrimitiveTypeRowProcessorAnnotationValidator;
import com.angel.io.validators.impl.InjectObjectRowProcessorAnnotationValidator;
import com.angel.io.validators.impl.OnlyOneRowProcessorAnnotationValidator;
import com.angel.io.validators.impl.RowProcessorCommandAnnotationValidator;
import com.angel.io.validators.impl.ZeroOrOneRowCheckerAnnotationValidator;

/**
 * @author William
 *
 */
public class ImportFileAnnotationProcessorRunner extends ImportFileProcessorRunner {

	private static final Logger LOGGER = Logger.getLogger(ImportFileAnnotationProcessorRunner.class);

	private List<RowProcessorCommandValidator> rowProcessorValidators;

	public ImportFileAnnotationProcessorRunner(FileProcessorDescriptor fileProcessorDescriptor, ImportFileProcessorCommand importFileCommand, Object rowProcessorCommand){
		super(fileProcessorDescriptor, importFileCommand);
		this.setRowProcessorValidators(new ArrayList<RowProcessorCommandValidator>());
		this.initializeRowProcessorValidators();
		this.validateRorProcessorCommand(rowProcessorCommand);
		this.setImportRowCommand(new AnnotationImportRowProcessorCommand(rowProcessorCommand));
	}

	protected void validateRorProcessorCommand(Object rowProcessorCommand){
		LOGGER.debug("Validating row processor command object [" + rowProcessorCommand.getClass() + "].");
		for(RowProcessorCommandValidator c: this.getRowProcessorValidators()){
			LOGGER.debug("Validating object [" + rowProcessorCommand.getClass() + "] with validator [" + c.getClass() + "].");
			c.validate(rowProcessorCommand.getClass());
		}
	}

	protected void initializeRowProcessorValidators(){
		this.addRowProcessorValidator(new OnlyOneRowProcessorAnnotationValidator());
		this.addRowProcessorValidator(new ZeroOrOneRowCheckerAnnotationValidator());
		this.addRowProcessorValidator(new RowProcessorCommandAnnotationValidator());
		this.addRowProcessorValidator(new DefaultConstructorRowProcessorCommandValidator());
		this.addRowProcessorValidator(new InjectObjectPrimitiveTypeRowProcessorAnnotationValidator());
		this.addRowProcessorValidator(new ColumnsParametersRowProcessorAnnotationValidator());
		this.addRowProcessorValidator(new ColumnsParametersRowCheckerAnnotationValidator());
		this.addRowProcessorValidator(new ColumnsPositionRowProcessorAnnotationValidator());
		this.addRowProcessorValidator(new ColumnsPositionRowCheckerAnnotationValidator());
		this.addRowProcessorValidator(new InjectObjectRowProcessorAnnotationValidator());
	}

	@Override
	public Object getImportRowCommand(){
		return ((AnnotationImportRowProcessorCommand)super.getImportRowCommand()).getRowProcessorCommand();
	}

	protected AnnotationImportRowProcessorCommand getAnnotationImportRowProcessorCommand(){
		return ((AnnotationImportRowProcessorCommand)super.getImportRowCommand());
	}

	/**
	 * @return the rowProcessorValidators
	 */
	protected List<RowProcessorCommandValidator> getRowProcessorValidators() {
		return rowProcessorValidators;
	}

	@Override
	protected void updateHeaderRow(ImportRowFile rowFile) {
		LOGGER.debug("Updating annotation header row.");
		Object importRowCommand = this.getImportRowCommand();
		RowProcessorCommand rowProcessorCommand = AnnotationHelper.getAnnotation(importRowCommand.getClass(), RowProcessorCommand.class);
		int i = 0;
		for(ColumnRow columnRow : rowProcessorCommand.columnsRow()){
			super.getHeaderRow().addColumn(i, columnRow.columnName());
			Collection<String> aliasesNames = CollectionHelper.convertGenericTo(columnRow.aliases());
			super.getHeaderRow().addAllAliasFor(columnRow.columnName(), aliasesNames);
			i++;
		}
	}

	/**
	 * @param rowProcessorValidators the rowProcessorValidators to set
	 */
	protected void setRowProcessorValidators(
			List<RowProcessorCommandValidator> rowProcessorValidators) {
		this.rowProcessorValidators = rowProcessorValidators;
	}

	public void addRowProcessorValidator(RowProcessorCommandValidator processorCommandValidator){
		this.getRowProcessorValidators().add(processorCommandValidator);
	}

	public boolean containsRowProcessorValidator(RowProcessorCommandValidator processorCommandValidator){
		return this.getRowProcessorValidators().contains(processorCommandValidator);
	}

	public void removeRowProcessorValidator(RowProcessorCommandValidator processorCommandValidator){
		this.getRowProcessorValidators().remove(processorCommandValidator);
	}
}
